package com.example.dnp_plugin

import android.Manifest
import android.app.Activity
import android.app.ActivityManager
import android.app.AlertDialog
import android.app.ProgressDialog
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.pm.PackageManager
import android.database.Cursor
import android.graphics.Bitmap
import android.location.Location
import android.location.LocationListener
import android.location.LocationManager
import android.net.ConnectivityManager
import android.net.NetworkInfo
import android.net.Uri
import android.net.wifi.WifiManager
import android.os.BatteryManager
import android.os.Build
import android.os.Bundle
import android.provider.ContactsContract
import android.provider.MediaStore
import android.widget.Toast
import androidx.annotation.NonNull
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import io.flutter.embedding.engine.plugins.FlutterPlugin
import io.flutter.embedding.engine.plugins.activity.ActivityAware
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.MethodChannel.MethodCallHandler
import io.flutter.plugin.common.MethodChannel.Result
import io.flutter.plugin.common.PluginRegistry
import java.io.ByteArrayOutputStream
import java.io.File
import java.io.FileOutputStream
import java.util.UUID

/** DnpPlugin */
class DnpPlugin : FlutterPlugin, MethodCallHandler, ActivityAware, PluginRegistry.ActivityResultListener,
    PluginRegistry.RequestPermissionsResultListener {

    private lateinit var channel: MethodChannel
    private var activity: Activity? = null
    private var context: Context? = null
    private var progressDialog: ProgressDialog? = null
    private var pendingResult: Result? = null
    private var locationManager: LocationManager? = null
    private var locationListener: LocationListener? = null

    companion object {
        private const val REQUEST_IMAGE_PICKER = 1001
        private const val REQUEST_CAMERA = 1002
        private const val REQUEST_CONTACT = 1003
        private const val REQUEST_LOCATION_PERMISSION = 2001
        private const val REQUEST_CAMERA_PERMISSION = 2002
        private const val REQUEST_STORAGE_PERMISSION = 2003
        private const val REQUEST_CONTACTS_PERMISSION = 2004
    }

    override fun onAttachedToEngine(flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
        channel = MethodChannel(flutterPluginBinding.binaryMessenger, "dnp_plugin")
        channel.setMethodCallHandler(this)
        context = flutterPluginBinding.applicationContext
    }

    override fun onMethodCall(call: MethodCall, result: Result) {
        when (call.method) {
            "getPlatformVersion" -> {
                result.success("Android ${Build.VERSION.RELEASE}")
            }
            "holiday" -> {
                result.success(Build.BRAND)
            }
            "cannot" -> {
                result.success(Build.MODEL)
            }
            "footed" -> {
                result.success(Build.MANUFACTURER)
            }
            "considerably" -> {
                result.success(Build.FINGERPRINT)
            }
            "fearlessness" -> {
                result.success(UUID.randomUUID().toString())
            }
            "sysName" -> {
                result.success("Android")
            }
            "afford" -> {
                result.success(Build.VERSION.RELEASE)
            }
            "largest" -> {
                result.success(Build.VERSION.SDK_INT.toString())
            }
            "autou" -> {
                result.success(Build.HARDWARE)
            }
            "ten" -> {
                result.success(Build.PRODUCT)
            }
            "should" -> {
                result.success(Build.DEVICE)
            }
            "finger" -> {
                result.success(Build.DISPLAY)
            }
            "showToast" -> {
                showToast(call, result)
            }
            "showAlert" -> {
                showAlert(call, result)
            }
            "openHud" -> {
                openHud(result)
            }
            "closeHud" -> {
                closeHud(result)
            }
            "submitFB" -> {
                submitFB(call, result)
            }
            "showSKStore" -> {
                showSKStore(result)
            }
            "showActionSheet" -> {
                showActionSheet(result)
            }
            "chooseContact" -> {
                chooseContact(result)
            }
            "chooseContactList" -> {
                chooseContactList(result)
            }
            "treasures" -> {
                getTreasures(result)
            }
            "indescribable" -> {
                getIndescribable(result)
            }
            "startLocationTracking" -> {
                startLocationTracking(result)
            }
            "endLocationTracking" -> {
                endLocationTracking(result)
            }
            "shook" -> {
                getShook(result)
            }
            "wire" -> {
                getWire(result)
            }
            else -> {
                result.notImplemented()
            }
        }
    }

    // Toast implementation
    private fun showToast(call: MethodCall, result: Result) {
        val message = call.arguments as? String ?: "No message"
        activity?.runOnUiThread {
            Toast.makeText(context, message, Toast.LENGTH_SHORT).show()
        }
        result.success(null)
    }

    // Alert Dialog implementation
    private fun showAlert(call: MethodCall, result: Result) {
        val message = call.arguments as? String ?: "No message"
        activity?.runOnUiThread {
            AlertDialog.Builder(activity)
                .setMessage(message)
                .setPositiveButton("OK") { dialog, _ ->
                    dialog.dismiss()
                }
                .show()
        }
        result.success(null)
    }

    // Loading HUD implementation
    private fun openHud(result: Result) {
        activity?.runOnUiThread {
            if (progressDialog == null) {
                progressDialog = ProgressDialog(activity).apply {
                    setMessage("Loading...")
                    setCancelable(false)
                }
            }
            progressDialog?.show()
        }
        result.success(null)
    }

    private fun closeHud(result: Result) {
        activity?.runOnUiThread {
            progressDialog?.dismiss()
        }
        result.success(null)
    }

    // Submit Feedback
    private fun submitFB(call: MethodCall, result: Result) {
        val params = call.arguments as? Map<*, *>
        val ta = params?.get("ta") as? String ?: ""
        val hou = params?.get("hou") as? String ?: ""
        val ex = params?.get("ex") as? String ?: ""
        val panta = params?.get("panta") as? String ?: ""
        
        // Log the feedback data (in a real app, you would send this to a server)
        android.util.Log.d("DnpPlugin", "Feedback - ta: $ta, hou: $hou, ex: $ex, panta: $panta")
        
        result.success(null)
    }

    // Show App Store Review (Google Play In-App Review)
    private fun showSKStore(result: Result) {
        activity?.runOnUiThread {
            try {
                val uri = Uri.parse("market://details?id=${context?.packageName}")
                val intent = Intent(Intent.ACTION_VIEW, uri)
                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
                activity?.startActivity(intent)
            } catch (e: Exception) {
                // Fallback to browser
                val uri = Uri.parse("https://play.google.com/store/apps/details?id=${context?.packageName}")
                val intent = Intent(Intent.ACTION_VIEW, uri)
                activity?.startActivity(intent)
            }
        }
        result.success(null)
    }

    // Action Sheet (Camera or Gallery)
    private fun showActionSheet(result: Result) {
        pendingResult = result
        activity?.runOnUiThread {
            AlertDialog.Builder(activity)
                .setTitle("Choose Image Source")
                .setItems(arrayOf("Camera", "Gallery")) { dialog, which ->
                    when (which) {
                        0 -> openCamera()
                        1 -> openGallery()
                    }
                    dialog.dismiss()
                }
                .setNegativeButton("Cancel") { dialog, _ ->
                    pendingResult?.success(null)
                    pendingResult = null
                    dialog.dismiss()
                }
                .show()
        }
    }

    private fun openCamera() {
        if (ContextCompat.checkSelfPermission(context!!, Manifest.permission.CAMERA) 
            != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(
                activity!!,
                arrayOf(Manifest.permission.CAMERA),
                REQUEST_CAMERA_PERMISSION
            )
        } else {
            launchCamera()
        }
    }

    private fun launchCamera() {
        val intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
        activity?.startActivityForResult(intent, REQUEST_CAMERA)
    }

    private fun openGallery() {
        if (ContextCompat.checkSelfPermission(context!!, Manifest.permission.READ_EXTERNAL_STORAGE) 
            != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(
                activity!!,
                arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE),
                REQUEST_STORAGE_PERMISSION
            )
        } else {
            launchGallery()
        }
    }

    private fun launchGallery() {
        val intent = Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI)
        activity?.startActivityForResult(intent, REQUEST_IMAGE_PICKER)
    }

    // Choose Contact
    private fun chooseContact(result: Result) {
        pendingResult = result
        if (ContextCompat.checkSelfPermission(context!!, Manifest.permission.READ_CONTACTS) 
            != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(
                activity!!,
                arrayOf(Manifest.permission.READ_CONTACTS),
                REQUEST_CONTACTS_PERMISSION
            )
        } else {
            launchContactPicker()
        }
    }

    private fun launchContactPicker() {
        val intent = Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI)
        activity?.startActivityForResult(intent, REQUEST_CONTACT)
    }

    // Choose Contact List
    private fun chooseContactList(result: Result) {
        if (ContextCompat.checkSelfPermission(context!!, Manifest.permission.READ_CONTACTS) 
            != PackageManager.PERMISSION_GRANTED) {
            result.error("PERMISSION_DENIED", "Contacts permission not granted", null)
            return
        }

        val contacts = mutableListOf<Map<String, String>>()
        val cursor: Cursor? = context?.contentResolver?.query(
            ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
            null,
            null,
            null,
            null
        )

        cursor?.use {
            val nameIndex = it.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME)
            val numberIndex = it.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)

            while (it.moveToNext()) {
                val name = if (nameIndex >= 0) it.getString(nameIndex) else ""
                val number = if (numberIndex >= 0) it.getString(numberIndex) else ""
                
                contacts.add(mapOf(
                    "name" to name,
                    "phone" to number
                ))
            }
        }

        result.success(contacts)
    }

    // Get Memory Info (treasures)
    private fun getTreasures(result: Result) {
        context?.let { ctx ->
            val activityManager = ctx.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
            val memInfo = ActivityManager.MemoryInfo()
            activityManager.getMemoryInfo(memInfo)

            val memoryInfo = mapOf(
                "totalMem" to memInfo.totalMem.toString(),
                "availMem" to memInfo.availMem.toString(),
                "lowMemory" to memInfo.lowMemory,
                "threshold" to memInfo.threshold.toString()
            )
            result.success(memoryInfo)
        } ?: result.error("CONTEXT_NULL", "Context is null", null)
    }

    // Get Location (indescribable)
    private fun getIndescribable(result: Result) {
        if (ContextCompat.checkSelfPermission(context!!, Manifest.permission.ACCESS_FINE_LOCATION) 
            != PackageManager.PERMISSION_GRANTED) {
            result.error("PERMISSION_DENIED", "Location permission not granted", null)
            return
        }

        locationManager = context?.getSystemService(Context.LOCATION_SERVICE) as? LocationManager
        
        try {
            val location = locationManager?.getLastKnownLocation(LocationManager.GPS_PROVIDER)
                ?: locationManager?.getLastKnownLocation(LocationManager.NETWORK_PROVIDER)

            if (location != null) {
                val locationInfo = mapOf(
                    "latitude" to location.latitude,
                    "longitude" to location.longitude,
                    "altitude" to location.altitude,
                    "accuracy" to location.accuracy
                )
                result.success(locationInfo)
            } else {
                result.success(mapOf(
                    "latitude" to 0.0,
                    "longitude" to 0.0,
                    "altitude" to 0.0,
                    "accuracy" to 0.0
                ))
            }
        } catch (e: SecurityException) {
            result.error("SECURITY_ERROR", e.message, null)
        }
    }

    // Start Location Tracking
    private fun startLocationTracking(result: Result) {
        if (ContextCompat.checkSelfPermission(context!!, Manifest.permission.ACCESS_FINE_LOCATION) 
            != PackageManager.PERMISSION_GRANTED) {
            result.error("PERMISSION_DENIED", "Location permission not granted", null)
            return
        }

        locationManager = context?.getSystemService(Context.LOCATION_SERVICE) as? LocationManager
        
        locationListener = object : LocationListener {
            override fun onLocationChanged(location: Location) {
                val locationInfo = mapOf(
                    "latitude" to location.latitude,
                    "longitude" to location.longitude,
                    "altitude" to location.altitude,
                    "accuracy" to location.accuracy
                )
                // In a real implementation, you might want to use an event channel for continuous updates
                android.util.Log.d("DnpPlugin", "Location updated: $locationInfo")
            }

            override fun onStatusChanged(provider: String?, status: Int, extras: Bundle?) {}
            override fun onProviderEnabled(provider: String) {}
            override fun onProviderDisabled(provider: String) {}
        }

        try {
            locationManager?.requestLocationUpdates(
                LocationManager.GPS_PROVIDER,
                1000L, // 1 second
                10f,   // 10 meters
                locationListener!!
            )
            
            val lastLocation = locationManager?.getLastKnownLocation(LocationManager.GPS_PROVIDER)
                ?: locationManager?.getLastKnownLocation(LocationManager.NETWORK_PROVIDER)
            
            val locationInfo = if (lastLocation != null) {
                mapOf(
                    "latitude" to lastLocation.latitude,
                    "longitude" to lastLocation.longitude,
                    "altitude" to lastLocation.altitude,
                    "accuracy" to lastLocation.accuracy
                )
            } else {
                mapOf(
                    "latitude" to 0.0,
                    "longitude" to 0.0,
                    "altitude" to 0.0,
                    "accuracy" to 0.0
                )
            }
            result.success(locationInfo)
        } catch (e: SecurityException) {
            result.error("SECURITY_ERROR", e.message, null)
        }
    }

    // End Location Tracking
    private fun endLocationTracking(result: Result) {
        locationListener?.let {
            locationManager?.removeUpdates(it)
            locationListener = null
        }
        result.success(null)
    }

    // Get WiFi Info (shook)
    private fun getShook(result: Result) {
        context?.let { ctx ->
            val wifiManager = ctx.applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager
            val wifiInfo = wifiManager.connectionInfo
            
            val info = mapOf(
                "ssid" to (wifiInfo.ssid ?: ""),
                "bssid" to (wifiInfo.bssid ?: ""),
                "ipAddress" to wifiInfo.ipAddress.toString(),
                "macAddress" to (wifiInfo.macAddress ?: ""),
                "rssi" to wifiInfo.rssi,
                "linkSpeed" to wifiInfo.linkSpeed
            )
            result.success(info)
        } ?: result.error("CONTEXT_NULL", "Context is null", null)
    }

    // Get Battery Info (wire)
    private fun getWire(result: Result) {
        context?.let { ctx ->
            val batteryStatus: Intent? = IntentFilter(Intent.ACTION_BATTERY_CHANGED).let { ifilter ->
                ctx.registerReceiver(null, ifilter)
            }

            val level = batteryStatus?.getIntExtra(BatteryManager.EXTRA_LEVEL, -1) ?: -1
            val scale = batteryStatus?.getIntExtra(BatteryManager.EXTRA_SCALE, -1) ?: -1
            val batteryPct = level * 100 / scale.toFloat()

            val status = batteryStatus?.getIntExtra(BatteryManager.EXTRA_STATUS, -1) ?: -1
            val isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING ||
                    status == BatteryManager.BATTERY_STATUS_FULL

            val info = mapOf(
                "level" to batteryPct,
                "isCharging" to isCharging,
                "status" to status
            )
            result.success(info)
        } ?: result.error("CONTEXT_NULL", "Context is null", null)
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?): Boolean {
        if (resultCode != Activity.RESULT_OK) {
            pendingResult?.success(null)
            pendingResult = null
            return false
        }

        when (requestCode) {
            REQUEST_IMAGE_PICKER, REQUEST_CAMERA -> {
                handleImageResult(data, requestCode)
                return true
            }
            REQUEST_CONTACT -> {
                handleContactResult(data)
                return true
            }
        }
        return false
    }

    private fun handleImageResult(data: Intent?, requestCode: Int) {
        try {
            val bitmap: Bitmap? = when {
                data?.data != null -> {
                    // Gallery
                    MediaStore.Images.Media.getBitmap(context?.contentResolver, data.data)
                }
                data?.extras?.get("data") != null -> {
                    // Camera
                    data.extras?.get("data") as? Bitmap
                }
                else -> null
            }

            if (bitmap != null) {
                // Convert bitmap to JPEG bytes
                val outputStream = ByteArrayOutputStream()
                bitmap.compress(Bitmap.CompressFormat.JPEG, 80, outputStream)
                val imageBytes = outputStream.toByteArray()
                
                // Determine if camera was used
                val isCameraOpen = (requestCode == REQUEST_CAMERA)

                pendingResult?.success(mapOf(
                    "imageBytes" to imageBytes,
                    "isCameraOpen" to isCameraOpen
                ))
            } else {
                pendingResult?.success(null)
            }
        } catch (e: Exception) {
            pendingResult?.error("IMAGE_ERROR", e.message, null)
        }
        pendingResult = null
    }

    private fun handleContactResult(data: Intent?) {
        try {
            val contactUri: Uri? = data?.data
            if (contactUri != null) {
                val cursor = context?.contentResolver?.query(contactUri, null, null, null, null)
                cursor?.use {
                    if (it.moveToFirst()) {
                        val nameIndex = it.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME)
                        val idIndex = it.getColumnIndex(ContactsContract.Contacts._ID)
                        
                        val name = if (nameIndex >= 0) it.getString(nameIndex) else ""
                        val contactId = if (idIndex >= 0) it.getString(idIndex) else ""

                        // Get phone number
                        var phoneNumber = ""
                        val phoneCursor = context?.contentResolver?.query(
                            ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
                            null,
                            "${ContactsContract.CommonDataKinds.Phone.CONTACT_ID} = ?",
                            arrayOf(contactId),
                            null
                        )
                        phoneCursor?.use { pc ->
                            if (pc.moveToFirst()) {
                                val phoneIndex = pc.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)
                                phoneNumber = if (phoneIndex >= 0) pc.getString(phoneIndex) else ""
                            }
                        }

                        pendingResult?.success(mapOf(
                            "name" to name,
                            "phone" to phoneNumber
                        ))
                    }
                }
            } else {
                pendingResult?.success(null)
            }
        } catch (e: Exception) {
            pendingResult?.error("CONTACT_ERROR", e.message, null)
        }
        pendingResult = null
    }

    override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<out String>,
        grantResults: IntArray
    ): Boolean {
        when (requestCode) {
            REQUEST_CAMERA_PERMISSION -> {
                if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    launchCamera()
                } else {
                    pendingResult?.error("PERMISSION_DENIED", "Camera permission denied", null)
                    pendingResult = null
                }
                return true
            }
            REQUEST_STORAGE_PERMISSION -> {
                if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    launchGallery()
                } else {
                    pendingResult?.error("PERMISSION_DENIED", "Storage permission denied", null)
                    pendingResult = null
                }
                return true
            }
            REQUEST_CONTACTS_PERMISSION -> {
                if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    launchContactPicker()
                } else {
                    pendingResult?.error("PERMISSION_DENIED", "Contacts permission denied", null)
                    pendingResult = null
                }
                return true
            }
        }
        return false
    }

    override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) {
        channel.setMethodCallHandler(null)
        context = null
    }

    override fun onAttachedToActivity(binding: ActivityPluginBinding) {
        activity = binding.activity
        binding.addActivityResultListener(this)
        binding.addRequestPermissionsResultListener(this)
    }

    override fun onDetachedFromActivityForConfigChanges() {
        activity = null
    }

    override fun onReattachedToActivityForConfigChanges(binding: ActivityPluginBinding) {
        activity = binding.activity
        binding.addActivityResultListener(this)
        binding.addRequestPermissionsResultListener(this)
    }

    override fun onDetachedFromActivity() {
        activity = null
    }
}
